/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#include "core/结构数据.h"
#include "面/几何模型生成.h"
#include "线性代数/变换.h"

#include <矩阵.h>
#include <公共函数.h>

#include "basic_vec.h"
#include "面/面.h"


void f_graph_计算直线坐标(vec3 方向, float32 长度, uint32 细分, S_Vec3Array* data) {
	++细分;
	长度 /= 细分;

	f_core_array_resize((S_Array*)data, 细分 + 1);
	vec3* vert_ptr = data->ptr_userData;

	方向 = vec_normalize(方向);
	for (uint32 i = 0; i <= 细分; ++i) {
		vert_ptr[i] = 方向 * (长度 * i);
	}
}

void f_graph_计算圆坐标v3_JIT(const vec3 中心, const float32 半径, uint32 细分, S_Vec3Array* data) {
	vec3* 结果 = data->ptr_userData;
	
	float32 度数 = (360.0 / 细分);
	for (uint32 i = 0; i < 细分; ++i) {
		结果[i].x = 中心.x + cos(M_角度转弧度((float32)i * 度数)) * 半径;
		结果[i].y = 中心.y + 0.0;
		结果[i].z = 中心.z + sin(M_角度转弧度((float32)i * 度数)) * 半径;
	}
}

void f_graph_计算圆坐标3(const vec3 中心, const float32 半径, uint32 细分, vec3* 结果, E_轴向 轴向) {
	float32 度数 = (360.0 / 细分);

	switch (轴向) {
	case E_轴向::e_X:
		for (uint32 i = 0; i < 细分; ++i) {
			结果[i].x = 中心.x + 0.0;
			结果[i].y = 中心.y + cos(M_角度转弧度((float32)i * 度数)) * 半径;
			结果[i].z = 中心.z + sin(M_角度转弧度((float32)i * 度数)) * 半径;
		}
		break;
	case E_轴向::e_Y:
		for (uint32 i = 0; i < 细分; ++i) {
			结果[i].x = 中心.x + cos(M_角度转弧度((float32)i * 度数)) * 半径;
			结果[i].y = 中心.y + 0.0;
			结果[i].z = 中心.z + sin(M_角度转弧度((float32)i * 度数)) * 半径;
		}
		break;
	case E_轴向::e_Z:
		for (uint32 i = 0; i < 细分; ++i) {
			结果[i].x = 中心.x + cos(M_角度转弧度((float32)i * 度数)) * 半径;
			结果[i].y = 中心.y + sin(M_角度转弧度((float32)i * 度数)) * 半径;
			结果[i].z = 中心.z + 0.0;
		}
		break;
	}
}

void f_graph_构建范围体素坐标(vec3 大小, uvec3 细分, S_Vec3Array* data, bool 以长度为单元, bool 中心) {
	细分.x = DEF_Max(细分.x, 1);
	细分.y = DEF_Max(细分.y, 1);

	if(!以长度为单元) 大小 /= 细分;
	
	f_core_array_resize((S_Array*)data, 细分.x * 细分.y * 细分.z);

	uint32 层  = 细分.x * 细分.z;

	vec3 中心偏移{};
	if (中心) {
		//ivec3 细分数 = {细分.x > 1 ? 细分.x : 0, 细分.y > 1 ? 细分.y : 0, 细分.z > 1 ? 细分.z : 0 };
		中心偏移 = 大小 * (细分 - 1) * 0.5;
		//if (以长度为单元) {
		//	
		//}
		//else {
		//	中心偏移 = 大小 * 0.5;
		//	if (细分.x <= 1) 中心偏移.x = 0;
		//	if (细分.y <= 1) 中心偏移.y = 0;
		//	if (细分.z <= 1) 中心偏移.z = 0;
		//}
		//中心偏移 = 以长度为单元 ? 大小 * (细分 - 1) * 0.5 : 大小 * 0.5;
	}

	#pragma omp parallel for num_threads(DEF_Min(16, int32(细分.y)))
	for (int32 y = 0; y < 细分.y; ++y) {
		for (int32 z = 0; z < 细分.z; ++z) {
			for (int32 x = 0; x < 细分.x; ++x) {
				uint32 index = 层 * y + 细分.x * z + x;
				vec3 c = { 大小.x * x - 中心偏移.x, 大小.y * y - 中心偏移.y, 大小.z * z - 中心偏移.z };
				//if(中心) c -= c * 0.5;
				data->ptr_userData[index] = c;
			}
		}
	}

	f_core_array_setDim((S_Array*)data, _iVec3(细分));
	f_core_array_setUnitSize((S_Array*)data, 大小);
}


uvec2 f_graph_构建球体(uint32 经度细分, uint32 维度细分, float32 半径, DEF_3Fs& V, DEF_3Fs& N, DEF_2Fs& uv, DEF_Is& I, bool is三角) {
	经度细分 = DEF_Max(经度细分, 3);
	维度细分 = DEF_Max(维度细分, 2);

	V.resize(经度细分 * (维度细分-1) + 2);
	N.resize(经度细分 * (维度细分-1) + 2);

	
	uint32 端点偏移 = 1;

	uv.resize(V.size());
	vec2* uv_ptr = uv.data();


	//底部顶点
	vec3_填充(&V[0], 0.0, -半径, 0.0);
	//顶部顶点
	vec3_填充(&V[经度细分 * (维度细分-1) + 1], 0.0, 半径, 0.0);


	vec3_填充(&N[0], 0.0, -1.0, 0.0);
	vec3_填充(&N[经度细分 * (维度细分-1) + 1], 0.0, 1.0, 0.0);


	S_Tranform 变换;
	f_TranformInit(变换);

	矩阵_创建缩放矩阵v(缩放矩阵, (float32*)&变换.scale);


	//float32 坐标X[3] = { -半径, 0.0, 0.0 };
	float32	Normal[4] = { 0.0, -1.0, 0.0, 1.0 };
	vec4	NewNormal = { 0.0, 1.0, 0.0, 0.0 };
	float32	坐标Z[4] = { 0.0, -半径, 0.0, 1.0 };
	float32	变换后坐标[4] = { 0.0, 0.0, 0.0 , 0.0 };
	矩阵_创建移动矩阵v(移动矩阵, 坐标Z);


	float32 维度步进 = 180.0f / (float32)维度细分;
	float32 进度步进 = 360.0f / (float32)经度细分;

	for (uint16 纬度 = 0; 纬度 < 维度细分 - 1; ++纬度) {
		float32 当前维度 = 维度步进 * (float32)(纬度 + 1);

		矩阵_创建X旋转矩阵(X旋转矩阵, 当前维度);
		for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
			uint16 id = 纬度 * 经度细分 + 经度 + 端点偏移;

			float32 当前经度 = 进度步进 * (float32)(经度);

			矩阵_创建Y旋转矩阵(Y旋转矩阵, 当前经度);
			矩阵_创建单位矩阵4X4(变换矩阵);
			
			Mat4X4_相乘(&变换矩阵, &Y旋转矩阵);
			Mat4X4_相乘(&变换矩阵, &X旋转矩阵);


			vec3_填充(变换后坐标, 0.0);
			vec4_填充(&NewNormal, 0.0);
			MAT变换坐标4(&变换矩阵, 坐标Z, 变换后坐标);
			MAT变换坐标4(&变换矩阵, Normal, &NewNormal);
			

			vec3_填充(&V[id], (vec4*)变换后坐标);
			vec3_填充(&N[id], &NewNormal);
			uv_ptr[id].x = 纬度;
			uv_ptr[id].y = 经度;
		}
	}

	

	
	
	if (is三角) {
		I.resize( (经度细分 * (维度细分-2)) * 6 + (经度细分*6) );
	}
	else {
		I.resize( (经度细分 * (维度细分-2)) * 4 + (经度细分*6) );
	}
	

	auto 索引 = I.data();

	//底部盖
	索引[0] = 0;
	uint32 V1 = 0;
	uint32 V2 = 1;
	uint32 V3 = 2;
	uint32 V4 = 0;
	uint32 index = 0;


	//底部盖
	for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
		索引[index + 0] = V1;
		索引[index + 1] = V2;
		索引[index + 2] = V3;

		index += 3;

		V2 += 1;
		V3 += 1; if (V3 >= 经度细分 + 1) V3 = 1;
	}
	
	for (uint16 纬度 = 0; 纬度 < 维度细分 - 2; ++纬度) {
		for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
			uint32 idL1 = 纬度 * 经度细分 + 经度 + 端点偏移;
			uint32 idL2 = (纬度 + 1) * 经度细分 + 经度 + 端点偏移;


			V1 = idL1; V2 = idL2; V3 = idL1 + 1; V4 = idL2 + 1;

			if (经度 + 1 >= 经度细分) {
				V3 = 纬度 * 经度细分 + 端点偏移;
				V4 = (纬度 + 1) * 经度细分 + 端点偏移;
			}

			if (is三角) {
				索引[index + 0] = V1;
				索引[index + 1] = V2;
				索引[index + 2] = V3;
				index += 3;

				索引[index + 0] = V3;
				索引[index + 1] = V2;
				索引[index + 2] = V4;
				index += 3;
			}
			else {
				索引[index + 0] = V1;
				索引[index + 1] = V2;
				索引[index + 2] = V4;
				索引[index + 3] = V3;
				index += 4;
			}

		}
	}


	V1 = 经度细分 * (维度细分-1) + 端点偏移;
	//顶部盖
	for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
		uint32 idL1 = (维度细分 - 2) * 经度细分 + 经度 + 端点偏移;
		V2 = idL1; 
		
		if (经度 + 1 >= 经度细分) V3 = (维度细分 - 2) * 经度细分 + 端点偏移;
		else V3 = idL1 + 1;

		索引[index + 0] = V2;
		索引[index + 1] = V1;
		索引[index + 2] = V3;

		index += 3;
	}

	return {经度细分, 维度细分};
}



void f_graph_构建立方体(vec3 size, uvec3 细分, DEF_3Fs& V, DEF_3Fs& N, DEF_2Fs& uv, DEF_Is& I, bool is三角) {
	uint32 num = (细分.x + 1) * (细分.y + 1) * (细分.z + 1);
	V.resize(num);
	N.resize(num);

	uv.resize(V.size());
	vec2* uv_ptr = uv.data();


	size *= 0.5;
	V = {
		{-size.x, -size.y, -size.z},	//0
		{-size.x, size.y, -size.z},		//1
		{size.x, size.y, -size.z},		//2
		{size.x, -size.y, -size.z},		//3

		{-size.x, -size.y, size.z},		//4
		{-size.x, size.y, size.z},		//5
		{size.x, size.y, size.z},		//6
		{size.x, -size.y, size.z},		//7
	};



	if (is三角) {
		N.resize(8);
		for (uint32 i = 0; i < 8; ++i) {
			N[i] = vec_normalize2(V[i]);
		}

		I.resize(36);
		uvec3* ip = (uvec3*)I.data();
		ip[0] = { 0, 1, 2 };
		ip[1] = { 2, 3, 0 };

		ip[2] = { 3, 2, 6 };
		ip[3] = { 6, 7, 3 };

		ip[4] = { 7, 6, 5 };
		ip[5] = { 5, 4, 7 };

		ip[6] = { 4, 5, 1 };
		ip[7] = { 1, 0, 4 };

		ip[8] = { 1, 5, 6 };
		ip[9] = { 6, 2, 1 };

		ip[10] = { 4, 0, 3 };
		ip[11] = { 3, 7, 4 };

	}
	else {
		N.resize(8);
		for (uint32 i = 0; i < 8; ++i) {
			N[i] = vec_normalize2(V[i]);
		}

		I.resize(24);
		uvec4* ip = (uvec4*)I.data();
		ip[0] = { 5, 4, 7, 6 };		//+Z
		ip[1] = { 0, 1, 2, 3 };		//-Z

		ip[2] = { 2, 6, 7, 3 };		//+X
		ip[3] = { 5, 1, 0, 4 };		//-X

		ip[4] = { 5, 6, 2, 1 };		//+Y
		ip[5] = { 0, 3, 7, 4 };		//-Y

	}
	

}

void f_graph_构建圆柱体(vec2 size, uvec2 细分, DEF_3Fs& v, DEF_3Fs& n, DEF_2Fs& uv, DEF_Is& index, bool is三角) {
	细分.x = DEF_Max(细分.x, 3);
	细分.y = DEF_Max(细分.y, 1);

	size.x = DEF_Max(size.x, 0);
	size.y = DEF_Max(size.y, 0);

	

	std::vector<vec3> 圆(细分.x);
	f_graph_计算圆坐标3({0, size.y*0.5f, 0 }, size.x, 细分.x, 圆.data(), E_轴向::e_Y);
	
	std::vector<uint32> 圆索引A = f_Range<uint32>(0, 细分.x);
	圆索引A.push_back(0);

	uint32 num = 细分.x * 2 * 细分.y;
	v.clear();
	n.clear();
	uv.clear();
	index.clear();

	float32 上下步进 = size.y / 细分.y;
	for (uint32 i = 0; i <= 细分.y; ++i) {
		
		v.insert(v.end(), 圆.begin(), 圆.end());
		n.insert(n.end(), 圆.begin(), 圆.end());

		for (auto& e : 圆) e.y -= 上下步进;
	}
	v.push_back(vec3{ 0, size.y*0.5f, 0 });
	v.push_back(vec3{ 0, -size.y*0.5f, 0 });
	n.push_back({ 0,1,0 });
	n.push_back({0,-1,0});



	uv.resize(v.size());


	uint32 顶端顶点索引 = v.size() - 2;
	uint32 底端顶点索引 = v.size() - 1;

	
	if (is三角) {
		index.reserve(细分.x * 3 * 2 + 细分.x * 6 * 细分.y);

		for (uint32 i = 0; i < 细分.x; ++i) {
			index.emplace_back(圆索引A[i]);
			index.emplace_back(顶端顶点索引);
			index.emplace_back(圆索引A[i + 1]);
		}

		uint32 偏移A;
		uint32 偏移B;
		for (uint32 y = 0; y < 细分.y; ++y) {
			偏移A = 圆.size() * (y);
			偏移B = 圆.size() * (y + 1);
			for (uint32 i = 0; i < 细分.x; ++i) {
				index.emplace_back(圆索引A[i] + 偏移A);
				index.emplace_back(圆索引A[i + 1] + 偏移A);
				index.emplace_back(圆索引A[i] + 偏移B);

				index.emplace_back(圆索引A[i + 1] + 偏移A);
				index.emplace_back(圆索引A[i + 1] + 偏移B);
				index.emplace_back(圆索引A[i] + 偏移B);
			}
		}

		偏移A = 圆.size() * 细分.y;
		for (uint32 i = 0; i < 细分.x; ++i) {
			index.emplace_back(圆索引A[i] + 偏移A);
			index.emplace_back(底端顶点索引);
			index.emplace_back(圆索引A[i + 1] + 偏移A);
		}
	}
	else {
		
	}

}

void f_graph_构建圆锥体(vec2 size, uint32 细分, DEF_3Fs& v, DEF_3Fs& n, DEF_2Fs& uv, DEF_Is& index, DEF_Es& E, bool is三角) {
	细分 = DEF_Max(细分, 3);

	size.x = DEF_Max(size.x, 0);
	size.y = DEF_Max(size.y, 0);

	v.resize(细分);
	f_graph_计算圆坐标3({ 0, 0, 0 }, size.x, 细分, v.data(), E_轴向::e_Y);

	v.insert(v.begin(), vec3{});
	v.push_back({0, size.y, 0});

	uv.resize(v.size());
	n.resize(v.size());

	E.reserve(细分*6);

	for (uint32 i = 0; i < 细分; ++i) {
		index.push_back(i + 1);
		index.push_back(0);
		index.push_back(i + 2);

		E.push_back({i + 1, 0});
		E.push_back({0, i + 2});
		E.push_back({i + 2, i + 1});
	}
	index.back() = 1;
	E[E.size() - 1].x = 1;
	E[E.size() - 2].y = 1;

	uint32 end = v.size() - 1;
	for (uint32 i = 0; i < 细分; ++i) {
		index.push_back(i + 1);
		index.push_back(end);
		index.push_back(i + 2);

		E.push_back({i + 1, end});
		E.push_back({end, i + 2});
		E.push_back({i + 2, i + 1});
	}
	index.back() = 1;
	E[E.size() - 1].x = 1;
	E[E.size() - 2].y = 1;

}

void f_graph_构建立方体线框(vec3 size, uvec3 细分, DEF_3Fs& V, DEF_Is& I, bool is三角)
{
	V.resize(细分.x * 细分.y * 细分.z);

	V = {
		{-0.5f, -0.5f, -0.5f},		//0 -X-Y-Z
		{-0.5f, 0.5f, -0.5f},		//1 -X Y-Z
		{0.5f, 0.5f, -0.5f},		//2  X Y-Z
		{0.5f, -0.5f, -0.5f},		//3

		{-0.5f, -0.5f, 0.5f},		//4
		{-0.5f, 0.5f, 0.5f},		//5
		{0.5f, 0.5f, 0.5f},			//6
		{0.5f, -0.5f, 0.5f},		//7
	};

	I.resize(24);
	uvec2* ip = (uvec2*)I.data();
	ip[0] = { 5, 4 };
	ip[1] = { 6, 7 };
	ip[2] = { 2, 3 };
	ip[3] = { 1, 0 };



	ip[4] = { 4, 7 };
	ip[5] = { 7, 3 };
	ip[6] = { 3, 0 };
	ip[7] = { 0, 4 };



	ip[8] = { 5, 6 };
	ip[9] = { 6, 2 };
	ip[10] = { 2, 1 };
	ip[11] = { 1, 5 };
}

void f_graph_构建骨骼锥体(vec2 size, DEF_3Fs& V, DEF_3Fs& N, DEF_Is& I, bool is三角) {
	/*V = {
		{0.0f, 0.0f, 0.0f},		//0 -X-Y-Z

		{-size.y, size.y, size.y},		//0 -X-Y-Z
		{size.y, size.y, size.y},		//1 -X Y-Z
		{size.y, size.y, -size.y},		//2  X Y-Z
		{-size.y, size.y, -size.y},		//3

		{0.0f, size.x, 0.0f},		//4
	};*/

	/*V = {
		{0.0f, 0.0f, 0.0f},		//0 -X-Y-Z

		{size.y, -size.y, size.y},		//0 -X-Y-Z
		{size.y, size.y, size.y},		//1 -X Y-Z
		{size.y, size.y, -size.y},		//2  X Y-Z
		{size.y, -size.y, -size.y},		//3

		{size.x, 0.0f, 0.0f},		//4
	};*/

	V = {
		{0.0f, 0.0f, 0.0f},		//0 -X-Y-Z

		{-size.y, size.y, size.y},		//0 -X-Y-Z
		{size.y, size.y, size.y},		//1 -X Y-Z
		{size.y, -size.y, size.y},		//2  X Y-Z
		{-size.y, -size.y, size.y},		//3

		{0.0f, 0.0f, size.x},		//4
	};

	N = V;
	N[0] = { 0,-1,0 };


	I = {
		0,1,2,
		0,2,3,
		0,3,4,
		0,4,1,

		5,2,1,
		5,3,2,
		5,4,3,
		5,1,4,
	};
}

void f_graph_构建平面(vec2 size, uvec2 细分, DEF_3Fs& V, DEF_3Fs& N, DEF_2Fs& uv, DEF_Is& I, DEF_Es& E, bool is三角) {
	细分 = max(细分, { 1,1 });

	vec2 offset = size / 细分;

	uint32 offsetIndex = 0;
	if (is三角) {
		I.resize((细分.x) * (细分.y) * 3 * 2);
		uvec3* p_Index = (uvec3*)I.data();

		for (uint32 y = 0; y < 细分.y; ++y) {
			for (uint32 x = 0; x < 细分.x; ++x) {
				uint32 跨行 = (细分.x + 1) * (y + 1);

				p_Index[offsetIndex].x = (细分.x + 1) * y + x;
				p_Index[offsetIndex].y = 跨行 + x;
				p_Index[offsetIndex].z = 跨行 + x + 1;
				++offsetIndex;

				p_Index[offsetIndex].y = 跨行 + x + 1;
				p_Index[offsetIndex].z = (细分.x + 1) * y + (x + 1);
				p_Index[offsetIndex].x = (细分.x + 1) * y + x;
				++offsetIndex;
			}
		}
	}
	else {
		I.resize((细分.x) * (细分.y) * 4);
		uvec4* p_Index = (uvec4*)I.data();

		for (uint32 y = 0; y < 细分.y; ++y) {
			uint32 跨行 = (细分.x + 1) * (y + 1);
			uint32 当前行 = y * (细分.x + 1);

			for (uint32 x = 0; x < 细分.x; ++x) {
				
				
				p_Index[offsetIndex].x = 当前行 + x;
				p_Index[offsetIndex].y = 当前行 + x + 1;
				p_Index[offsetIndex].z = 跨行 + x + 1;
				p_Index[offsetIndex].w = 跨行 + x;
				++offsetIndex;


				E.push_back({当前行 + x, 当前行 + x + 1});
				E.push_back({当前行 + x, 跨行 + x});
			}
			E.push_back({当前行 + 细分.x, 跨行 + 细分.x});
		}
		//E.push_back({当前行 + 细分.x, 跨行 + 细分.x});
	}
	


	//添加边界顶点索引宽度
	细分.x += 1;
	细分.y += 1;
	uint32 顶点数量 = 细分.x * 细分.y;
	V.resize(顶点数量);
	N.resize(顶点数量);
	uv.resize(顶点数量);

	auto* p_Vert = V.data();
	auto* p_Normal = N.data();
	auto* p_UV = uv.data();


	offsetIndex = 0;
	vec3 负方向偏移 = { size.x * 0.5f, 0.0f, size.y * 0.5f };
	for (uint32 y = 0; y < 细分.y; ++y) {
		for (uint32 x = 0; x < 细分.x; ++x) {
			vec3 顶点 = {};
			vec2 UV;

			顶点.x = x * offset.x;
			顶点.z = y * offset.y;
			p_Vert[offsetIndex] = 顶点 - 负方向偏移;
			p_Normal[offsetIndex] = {0,1,0};

			UV.x = x / 细分.x;
			UV.y = y / 细分.y;
			p_UV[offsetIndex] = UV;

			++offsetIndex;
		}
	}

	//for (uint32 y = 0; y < 细分.y; ++y) {
	//	for (uint32 x = 0; x < 细分.x; ++x) {
	//		uint32 当前行 = y * (细分.x + 1);
	//		uint32 跨行 = (细分.x + 1) * (y + 1);
	//	}
	//}
}

void f_graph_构建交叉轴(DEF_3Fs& v, DEF_3Fs& n, DEF_2Fs& uv, DEF_Is& index) {
	v.resize(6);
	n.resize(6);
	uv.resize(6);
	index.resize(6);

	v[0] = { 0.5f, 0.0f, 0.0f };
	v[1] = { -0.5f, 0.0f, 0.0f };
	v[2] = { 0.0f, 0.5f, 0.0f };
	v[3] = { 0.0f, -0.5f, 0.0f };
	v[4] = { 0.0f, 0.0f, 0.5f };
	v[5] = { 0.0f, 0.0f, -0.5f };

	index[0] = 0;
	index[1] = 1;
	index[2] = 2;
	index[3] = 3;
	index[4] = 4;
	index[5] = 5;
}

void f_graph_构建方向轴(DEF_3Fs& v, DEF_3Fs& n, DEF_2Fs& uv, DEF_Is& index) {
	v.resize(4);
	n.resize(4);
	uv.resize(4);
	index.resize(6);

	v[0] = { 0.0f, 0.0f, 0.0f };
	v[1] = { 1.0f, 0.0f, 0.0f };
	v[2] = { 0.0f, 1.0f, 0.0f };
	v[3] = { 0.0f, 0.0f, 1.0f };

	index[0] = 0;
	index[1] = 1;
	index[2] = 0;
	index[3] = 2;
	index[4] = 0;
	index[5] = 3;
}

void f_graph_构建线框球(DEF_3Fs& v, DEF_3Fs& n, DEF_2Fs& uv, DEF_Is& index, uint32 细分) {
	v.resize(细分);
	n.resize(细分);
	uv.resize(细分);

	f_graph_计算圆坐标v3({}, 0.5, 细分, v.data());
	index = range<uint32>(0, 细分);
}










void f_graph_从面采样坐标(std::vector<S_VN>& rvn, const std::vector<S_VN>& vn, const std::vector<uvec3>& i, float32 间隔) {
	const uvec3* index = i.data();
	const S_VN* vert = vn.data();

	uint32 num = i.size();
	uint32 offset = 0;
	for (uint32 k = 0; k < num; ++k) {
		vec3 ea = vec_sub(vert[index[k].y].vert, vert[index[k].x].vert);
		vec3 eb = vec_sub(vert[index[k].z].vert, vert[index[k].y].vert);
		
		float32 la = vec_normalize(&ea);
		float32 lb = vec_normalize(&eb);

		float32 斜率 = la / lb;
		uint32 U长度 = la / 间隔;
		
		uint32 Vnum = DEF_Max(1, lb / 间隔 * (斜率));
		float32 跨度 = la / lb * 间隔;


		uint32 Unum = U长度;
		rvn.reserve(rvn.size() + Vnum * Unum);
		for (uint32 纵 = 0; 纵 < Vnum; ++纵) {
			float32 纵采样比例 = float32(纵) / float32(Vnum);
			vec3 采样坐标V = vec_mul(eb, 间隔 * 纵);
			
			Unum = DEF_Max(间隔, (la - 跨度 * 纵)) / 间隔;
			for (uint32 横 = 0; 横 < Unum; ++横) {
				vec3 采样坐标U = vec_mul(ea, 间隔 * (横) + (纵*跨度) );

				float32 横采样比例 = float32(横 + (U长度 - Unum)) / float32(U长度);
				vec3 采样法线V = vec_mix(vert[index[k].z].normal, vert[index[k].y].normal, float32(横) / float32(Unum));
				vec3 采样法线U = vec_mix(vert[index[k].x].normal, 采样法线V, 横采样比例);

				vec3 coord = vec_add(采样坐标V, 采样坐标U);
				vec_add(&coord, vert[index[k].x].vert);
				rvn.push_back({ coord, vec_normalize2(采样法线U) });
			}

			
		}
	}

}

void f_graph_平面(
	std::vector<S_VNTC>&	顶点, 
	std::vector<uint32>&	索引, 
	uvec2					细分, 
	const vec2&				size, 
	vec2					offset, 
	const S_RGBA8UI&		color, 
	E_轴向					轴向, 
	bool					面
) {
	细分 = max(细分, { 1,1 });

	

	uint32 offsetIndex = 0;
	索引.resize((细分.x) * (细分.y) * 4);
	uvec4* p_Index = (uvec4*)索引.data();

	for (uint32 y = 0; y < 细分.y; ++y) {
		uint32 跨行 = (细分.x + 1) * (y + 1);
		uint32 当前行 = y * (细分.x + 1);

		for (uint32 x = 0; x < 细分.x; ++x) {
		//for (uint32 x = 0; x < 3; ++x) {
			
			p_Index[offsetIndex].x = 当前行 + x;
			p_Index[offsetIndex].y = 当前行 + x + 1;
			p_Index[offsetIndex].z = 跨行 + x + 1;
			p_Index[offsetIndex].w = 跨行 + x;
			++offsetIndex;
		}
	}



	//添加边界顶点索引宽度
	细分.x += 1;
	细分.y += 1;
	uint32 顶点数量 = 细分.x * 细分.y;
	顶点.reserve(顶点数量);
	
	float32 顶点颜色 = UintBitFloat(f_PackData4X8(color));
	vec3 负方向偏移 = {};

	offset -= size * 0.5;
	switch (轴向) {
		case E_轴向::e_X: {
			负方向偏移 = { 0.0f, offset.x, offset.y };
			break;
		}
		case E_轴向::e_Y: {
			负方向偏移 = { offset.x, 0.0f, offset.y };
			break;
		}
		case E_轴向::e_Z: {
			负方向偏移 = { offset.x, offset.y, 0.0f };
			break;
		}
	}

	for (uint32 y = 0; y < 细分.y; ++y) {
		for (uint32 x = 0; x < 细分.x; ++x) {
			//vec3 顶点 = {};
			//vec2 UV;
			S_VNTC point{};

			switch (轴向) {
				case E_轴向::e_X: {
					point.vert.y = x * size.x;
					point.vert.z = y * size.y;
					break;
				}
				case E_轴向::e_Y: {
					point.vert.x = x * size.x;
					point.vert.z = y * size.y;
					break;
				}
				case E_轴向::e_Z: {
					point.vert.x = x * size.x;
					point.vert.y = y * size.y;
					break;
				}
			}
			point.vert += 负方向偏移;

			point.normal = {0,1,0};

			point.uv_color.x = x / 细分.x;
			point.uv_color.y = y / 细分.y;
			point.uv_color.z = 顶点颜色;

			顶点.emplace_back(point);
		}
	}
}

uvec2 f_graph_立方体线段(std::vector<S_VNTC>& 顶点, std::vector<uint32>& 索引, const vec3& size, const vec3& offset) {
	vec3 v = size * 0.5;

	uint32 顶点偏移 = 顶点.size();
	uint32 索引偏移 = 索引.size();

	uint32 num = 顶点.size();
	顶点.push_back({ offset + vec3{-v.x, -v.y, -v.z}, {}, {} });
	顶点.push_back({ offset + vec3{-v.x, v.y, -v.z}, {}, {} });
	顶点.push_back({ offset + vec3{v.x, v.y, -v.z}, {}, {} });
	顶点.push_back({ offset + vec3{v.x, -v.y, -v.z}, {}, {} });

	顶点.push_back({ offset + vec3{-v.x, -v.y, v.z}, {}, {} });
	顶点.push_back({ offset + vec3{-v.x, v.y, v.z}, {}, {} });
	顶点.push_back({ offset + vec3{v.x, v.y, v.z}, {}, {} });
	顶点.push_back({ offset + vec3{v.x, -v.y, v.z}, {}, {} });


	索引.push_back(0); 索引.push_back(1);
	索引.push_back(1); 索引.push_back(2);
	索引.push_back(2); 索引.push_back(3);
	索引.push_back(3); 索引.push_back(0);

	索引.push_back(4); 索引.push_back(5);
	索引.push_back(5); 索引.push_back(6);
	索引.push_back(6); 索引.push_back(7);
	索引.push_back(7); 索引.push_back(4);

	索引.push_back(0); 索引.push_back(4);
	索引.push_back(1); 索引.push_back(5);
	索引.push_back(2); 索引.push_back(6);
	索引.push_back(3); 索引.push_back(7);


	return { uint32(顶点.size() - 顶点偏移), uint32(索引.size() - 索引偏移) };
}

uint32 f_graph_立方体线段(std::vector<S_VC>& 顶点, const vec3& size, const vec3& offset, const S_RGBA8UI& color) {
	vec3 v = size * 0.5;

	uint32 colorPack = f_PackData4X8(color);
	uint32 num = 顶点.size();
	顶点.push_back({ offset + vec3{-v.x, -v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, -v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{-v.x, v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, v.y, -v.z}, colorPack });

	顶点.push_back({ offset + vec3{-v.x, v.y, v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, v.y, v.z}, colorPack });
	顶点.push_back({ offset + vec3{-v.x, -v.y, v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, -v.y, v.z}, colorPack });


	顶点.push_back({ offset + vec3{-v.x, -v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{-v.x, -v.y, v.z}, colorPack });
	顶点.push_back({ offset + vec3{-v.x, v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{-v.x, v.y, v.z}, colorPack });

	顶点.push_back({ offset + vec3{v.x, -v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, -v.y, v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, v.y, v.z}, colorPack });

	顶点.push_back({ offset + vec3{-v.x, v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{-v.x, -v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{-v.x, v.y, v.z}, colorPack });
	顶点.push_back({ offset + vec3{-v.x, -v.y, v.z}, colorPack });

	顶点.push_back({ offset + vec3{v.x, v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, -v.y, -v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, v.y, v.z}, colorPack });
	顶点.push_back({ offset + vec3{v.x, -v.y, v.z}, colorPack });

	return 顶点.size() - num;
}

uvec2 f_graph_立方体(std::vector<S_VC>& 顶点, std::vector<uint32>& 索引, const vec3& size, const vec3& offset, const S_RGBA8UI& color) {
	uint32 colorPack = f_PackData4X8(color);

	uint32 顶点偏移 = 顶点.size();
	uint32 索引偏移 = 索引.size();


	DEF_3Fs v;
	DEF_3Fs n;
	DEF_2Fs uv;
	DEF_Is i;
	f_graph_构建立方体(size, {1,1,1}, v, n, uv, i, true);

	顶点.reserve(顶点.size() + v.size());
	索引.reserve(索引.size() + i.size());

	
	//for (auto& e : v) {
	//	顶点.push_back({ offset + e, colorPack });
	//}
	for (auto& e : i) {
		索引.push_back(e);
	}
	for (auto& e : i) {
		顶点.push_back({ offset + v[e], colorPack });
	}

	return {uint32(顶点.size() - 顶点偏移), uint32(索引.size() - 索引偏移)};
}

uvec2 f_graph_圆(std::vector<S_VNTC>& 顶点, std::vector<uint32>& 索引, const float32 size, const vec3& offset, const S_RGBA8UI& color, E_轴向 轴向) {
	std::vector<vec2> 坐标(64);

	uint32 顶点偏移 = 顶点.size();
	uint32 索引偏移 = 索引.size();

	f_graph_计算圆坐标XY({offset.x, offset.y}, size, 64, 坐标.data());
	float32 顶点颜色 = UintBitFloat(f_PackData4X8(color));

	uint32 colorPack = f_PackData4X8(color);

	uint32 num = 坐标.size();
	//uint32 end = num -1;
	for (uint32 i=0; i<num; ++i) {
		auto& e1 = 坐标[i];
		//auto& e2 = 坐标[i+1];

		switch (轴向) {
		case E_轴向::e_X: {
			顶点.push_back({{ 0, e1.y, e1.x }, {}, {0,0,顶点颜色} });
			//顶点.push_back({{ 0, e2.y, e2.x }, {}, {0,0,顶点颜色} });
			break;
		}
		case E_轴向::e_Y: {
			顶点.push_back({{ e1.x, 0, e1.y }, {}, {0,0,顶点颜色} });
			//顶点.push_back({{ e2.x, 0, e2.y }, {}, {0,0,顶点颜色} });
			break;
		}
		case E_轴向::e_Z: {
			顶点.push_back({{ e1.x, e1.y, 0 }, {}, {0,0,顶点颜色} });
			//顶点.push_back({{ e2.x, e2.y, 0 }, {}, {0,0,顶点颜色} });
			break;
		}
		default:
			break;
		}

		索引.emplace_back(i);
		索引.emplace_back(i+1);
	}
	索引.back() = 0;

	//switch (轴向) {
	//case E_轴向::e_X: {
	//	顶点.push_back({{ 0, 坐标[end].y, 坐标[end].x }, {}, {} });
	//	顶点.push_back({{ 0, 坐标[0].y, 坐标[0].x }, {}, {} });
	//	break;
	//}
	//case E_轴向::e_Y: {
	//	顶点.push_back({{ 坐标[end].x, 0, 坐标[end].y }, {}, {} });
	//	顶点.push_back({{ 坐标[0].x, 0, 坐标[0].y }, {}, {} });
	//	break;
	//}
	//case E_轴向::e_Z: {
	//	顶点.push_back({{ 坐标[end].x, 坐标[end].y, 0 }, {}, {} });
	//	顶点.push_back({{ 坐标[0].x, 坐标[0].y, 0 }, {}, {} });
	//	break;
	//}
	//default:
	//	break;
	//}
	//
	//
	//for (uint32 i=0; i<64-1; ++i) {
	//	索引.push_back(i);
	//	索引.push_back(i+1);
	//}
	//索引.push_back(63);
	//索引.push_back(0);

	return {uint32(顶点.size() - 顶点偏移), uint32(索引.size() - 索引偏移)};
}

uvec2 f_graph_锥形(std::vector<S_VNTC>& 顶点, std::vector<uint32>& 索引, const vec3& 半径高度细分, const vec3& offset, const S_RGBA8UI& color, E_轴向 轴向, bool 面) {
	uint32 colorPack = f_PackData4X8(color);
	uint32 顶点偏移 = 顶点.size();
	uint32 索引偏移 = 索引.size();


	uint32 细分 = 半径高度细分.z;
	std::vector<vec2> 坐标(细分);
	f_graph_计算圆坐标XY({}, 半径高度细分.x, 细分, 坐标.data());
	float32 顶点颜色 = UintBitFloat(f_PackData4X8(color));

	if (面) {
		顶点.push_back({{ 0, 0, 0 }, {}, {0,0,顶点颜色}});
		for (auto& e : 坐标) {
			switch (轴向) {
				case E_轴向::e_X: {
					顶点.push_back({{ 0, e.y, e.x }, {}, {0,0,顶点颜色}});
					break;
				}
				case E_轴向::e_Y: {
					顶点.push_back({{ e.x, 0, e.y }, {}, {0,0,顶点颜色}});
					break;
				}
				case E_轴向::e_Z: {
					顶点.push_back({{ e.x, e.y, 0 }, {}, {0,0,顶点颜色}});
					break;
				}
			}
		}
		switch (轴向) {
			case E_轴向::e_X: {
				顶点.push_back({{ 半径高度细分.y, 0, 0 }, {}, {0,0,顶点颜色}});
				break;
			}
			case E_轴向::e_Y: {
				顶点.push_back({{ 0, 半径高度细分.y, 0 }, {}, {0,0,顶点颜色}});
				break;
			}
			case E_轴向::e_Z: {
				顶点.push_back({{ 0, 0, 半径高度细分.y }, {}, {0,0,顶点颜色}});
				break;
			}
		}

		

		uint32 end = 顶点.size() - 1;
		uint32 num = 细分 -1;

		for (uint32 i=0; i<num; ++i) {
			//auto& e1 = 坐标[i];
			//auto& e2 = 坐标[i+1];
			//switch (轴向) {
			//	case E_轴向::e_X: {
			//		顶点.push_back({{ 0, e1.y, e1.x }, {}, {0,0,顶点颜色}});
			//		顶点.push_back({{ 半径高度细分.y, 0, 0 }, {}, {0,0,顶点颜色} });
			//		顶点.push_back({{ 0, e2.y, e2.x }, {}, {0,0,顶点颜色} });
			//		break;
			//	}
			//	case E_轴向::e_Y: {
			//		顶点.push_back({{ e1.x, 0, e1.y }, {}, {0,0,顶点颜色} });
			//		顶点.push_back({{ 0, 半径高度细分.y, 0 }, {}, {0,0,顶点颜色} });
			//		顶点.push_back({{ e2.x, 0, e2.y }, {}, {0,0,顶点颜色} });
			//		break;
			//	}
			//	case E_轴向::e_Z: {
			//		顶点.push_back({{ e1.x, e1.y, 0 }, {}, {0,0,顶点颜色} });
			//		顶点.push_back({{ 0, 0, 半径高度细分.y }, {}, {0,0,顶点颜色} });
			//		顶点.push_back({{ e2.x, e2.y, 0 }, {}, {0,0,顶点颜色} });
			//		break;
			//	}
			//}

			索引.emplace_back(0);
			索引.emplace_back(i+1);
			索引.emplace_back(i+2);

			索引.emplace_back(i+2);
			索引.emplace_back(i+1);
			索引.emplace_back(end);


		}

		//switch (轴向) {
		//	case E_轴向::e_X: {
		//		顶点.push_back({{ 0, 坐标[end].y, 坐标[end].x }, {}, {0,0,顶点颜色} });
		//		顶点.push_back({{ 半径高度细分.y, 0, 0 }, {}, {0,0,顶点颜色} });
		//		顶点.push_back({{ 0, 坐标[0].y, 坐标[0].x }, {}, {0,0,顶点颜色} });
		//		break;
		//	}
		//	case E_轴向::e_Y: {
		//		顶点.push_back({{ 坐标[end].x, 0, 坐标[end].y }, {}, {0,0,顶点颜色} });
		//		顶点.push_back({{ 0, 半径高度细分.y, 0 }, {}, {0,0,顶点颜色} });
		//		顶点.push_back({{ 坐标[0].x, 0, 坐标[0].y }, {}, {0,0,顶点颜色} });
		//		break;
		//	}
		//	case E_轴向::e_Z: {
		//		顶点.push_back({{ 坐标[end].x, 坐标[end].y, 0 }, {}, {0,0,顶点颜色} });
		//		顶点.push_back({{ 0, 0, 半径高度细分.y }, {}, {0,0,顶点颜色} });
		//		顶点.push_back({{ 坐标[0].x, 坐标[0].y, 0 }, {}, {0,0,顶点颜色} });
		//		break;
		//	}
		//	default:
		//		break;
		//}

		索引.emplace_back(0);
		索引.emplace_back(num+1);
		索引.emplace_back(1);

		索引.emplace_back(1);
		索引.emplace_back(num+1);
		索引.emplace_back(end);
	}
	else {

	}
	

	return {uint32(顶点.size() - 顶点偏移), uint32(索引.size() - 索引偏移)};
}

/*void f_graph_添加间接绘制(std::vector<S_VkDrawIndirectCommand>& indirects, DEF_3Fs& v, DEF_Is& index) {
	
	S_VkDrawIndirectCommand indirect = {};
	indirect.vertexCount = v.size();
	indirect.instanceCount = 1;
	
	indirect.firstInstance = indirects.size();

	if (indirect.firstInstance) {
		S_VkDrawIndirectCommand end = indirects.back();
		indirect.firstVertex = end.firstVertex + end.vertexCount;
	}
	else {
		indirect.firstVertex = 0;
	}
}*/


void f_graph_合并(std::vector<S_VNT1>& vert, std::vector<uint32>& index, const std::vector<S_VNT1>& 追加顶点, const std::vector<uint32>& 追加索引) {
	uint32 顶点偏移 = vert.size();

	vert.insert(vert.end(), 追加顶点.begin(), 追加顶点.end());

	for (auto e : 追加索引) {
		index.push_back(e + 顶点偏移);
	}
}




